home *** CD-ROM | disk | FTP | other *** search
- ; AMSAT/TAPR DSP WEFAX demodulator
- ; Sample rate should be set to 10000 samples/sec.
- ; Code by Bob McGwier N4HY. Copyright 1988, ALL RIGHTS RESERVED!
- ;
- ; Needs: post frequency synthesis filtering and adaptive equalization
- ; to achieve "perfection" :-)
- org 0
- b go
- org 0FF0H
- dw 3932 ; 2400Hz at 10000 samples/sec
- ;
- ; Okay Jose' set up equates for data memory etc.
- ;
- org 10H ; code should begin at memory address 16 cause David
- ; does something strange with locations 0-15. Does
- ; he in fact document this? Is it a TMS32010 feature?
-
- sine: equ 0 ; will store sine values from tone
- one: equ 1 ; guess what goes here duhhhhh!
- freq: equ 2 ; PLL frequency stored here
- phase: equ 3 ; PLL phase stored here
- maskl: equ 4 ; mask for fine or low order bits of phase
- mask: equ 5 ; mask for doing modulo 16384 arithmetic with phase
- sinx: equ 6 ; used to store coarse sine value (high order bits)
- cosx: equ 7 ; as above for cosine
- mone: equ 8 ; minus one stored here
- wkph: equ 9 ; different phases (PLL, remodulator tone etc) are stored hr
- ; for frequency synthesis
- masko: equ 10 ; mask for converting on board PCM to DAC format
- mps: equ 11 ; multiplier for quadrant determination for sine
- mpc: equ 12 ; multiplier for quadrant determination for cosine
- siny: equ 13 ; fine correction value for use in SIN(X+Y) = sinx*cosy+
- cosy: equ 14 ; cosx*siny
- cosine: equ 15 ; cosine is also needed for Q arm in Costas loop
- coph: equ 16 ; working number holder
- modem: equ 17 ; Used to choose between complex tone for arms and real tone
- ; in the modulator as explained below
- contr: equ 18
-
- freqo: equ 20 ; freqo is assigned one of the values above for remod
- phaseo: equ 71 ; phaseo is the phase of the remodulator output. phase is
- ; as continuous as DSP will allow on this board
- xn0: equ 21 ; place for storing all the values for the "I" or data arm
- xn1: equ 22
- xn2: equ 23
- xn3: equ 24
- xn4: equ 25
- xn5: equ 26
- xn6: equ 27
- xn7: equ 28
- xn8: equ 29
- xn9: equ 30
- xn10: equ 31
- xn11: equ 32
- xn12: equ 33
- xn13: equ 34
- xn14: equ 35
- xn15: equ 36
- xn16: equ 37
- xn17: equ 38
- xn18: equ 39
- xn19: equ 40
- xn20: equ 41
- xn21: equ 42
- xn22: equ 43
- xn23: equ 44
- yn0: equ 45 ; storage for values in "Q" or phase error arm.
- yn1: equ 46
- yn2: equ 47
- yn3: equ 48
- yn4: equ 49
- yn5: equ 50
- yn6: equ 51
- yn7: equ 52
- yn8: equ 53
- yn9: equ 54
- yn10: equ 55
- yn11: equ 56
- yn12: equ 57
- yn13: equ 58
- yn14: equ 59
- yn15: equ 60
- yn16: equ 61
- yn17: equ 62
- yn18: equ 63
- yn19: equ 64
- yn20: equ 65
- yn21: equ 66
- yn22: equ 67
- yn23: equ 68
- c0: equ 69 ; Phase error
- maskf: equ 70 ; frequency mask so that frequency doesn't try and leave
- ; proper range
- tester: equ 72 ; remodulator output -300 to 300 millivolts on DAC's
- data: equ 73
- h10: equ 74
- h11: equ 75
- armfilt: dw 6861
- dw 9601
- sintbl: dw 0 ; coarse sine table in steps of PI/64 radians to PI/2
- dw 804
- dw 1607
- dw 2410
- dw 3211
- dw 4011
- dw 4807
- dw 5601
- dw 6392
- dw 7179
- dw 7961
- dw 8739
- dw 9511
- dw 10278
- dw 11038
- dw 11792
- dw 12539
- dw 13278
- dw 14009
- dw 14732
- dw 15446
- dw 16150
- dw 16845
- dw 17530
- dw 18204
- dw 18867
- dw 19519
- dw 20159
- dw 20787
- dw 21402
- dw 22004
- dw 22594
- dw 23169
- dw 23731
- dw 24278
- dw 24811
- dw 25329
- dw 25831
- dw 26318
- dw 26789
- dw 27244
- dw 27683
- dw 28105
- dw 28510
- dw 28897
- dw 29268
- dw 29621
- dw 29955
- dw 30272
- dw 30571
- dw 30851
- dw 31113
- dw 31356
- dw 31580
- dw 31785
- dw 31970
- dw 32137
- dw 32284
- dw 32412
- dw 32520
- dw 32609
- dw 32678
- dw 32727
- dw 32757
- dw 32767 ; PI/2
- fines: dw 0 ; fine sine table in steps of PI/(64*64) radians to PI/64
- dw 12
- dw 25
- dw 37
- dw 50
- dw 62
- dw 75
- dw 87
- dw 100
- dw 113
- dw 125
- dw 138
- dw 150
- dw 163
- dw 175
- dw 188
- dw 201
- dw 213
- dw 226
- dw 238
- dw 251
- dw 263
- dw 276
- dw 289
- dw 301
- dw 314
- dw 326
- dw 339
- dw 351
- dw 364
- dw 376
- dw 389
- dw 402
- dw 414
- dw 427
- dw 439
- dw 452
- dw 464
- dw 477
- dw 490
- dw 502
- dw 515
- dw 527
- dw 540
- dw 552
- dw 565
- dw 578
- dw 590
- dw 603
- dw 615
- dw 628
- dw 640
- dw 653
- dw 665
- dw 678
- dw 691
- dw 703
- dw 716
- dw 728
- dw 741
- dw 753
- dw 766
- dw 779
- dw 791
- finec: dw 32767 ;ditto to above for fine sine
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32766
- dw 32765
- dw 32765
- dw 32765
- dw 32765
- dw 32765
- dw 32765
- dw 32765
- dw 32765
- dw 32764
- dw 32764
- dw 32764
- dw 32764
- dw 32764
- dw 32764
- dw 32764
- dw 32763
- dw 32763
- dw 32763
- dw 32763
- dw 32763
- dw 32762
- dw 32762
- dw 32762
- dw 32762
- dw 32762
- dw 32761
- dw 32761
- dw 32761
- dw 32761
- dw 32760
- dw 32760
- dw 32760
- dw 32760
- dw 32759
- dw 32759
- dw 32759
- dw 32759
- dw 32758
- dw 32758
- dw 32758
- dw 32758
- dw 32757
- dw 32757
- go: ldpk 0 ; make sure that we are pointing to 0 data page
- lack one ; make and store one
- sacl one
- lac one,11 ; make and store DAC converter mask
- sacl masko
- lac one,13 ; make and store frequency mask
- sub one
- sacl maskf
- zac
- sub one
- sacl mone ; make and store minus one
- lac one,14
- sub one
- sacl mask ; make and store mask for modulo 16384 phase arithmetic
- lac one,6
- sub one
- sacl maskl ; make and store fine part of address mask;
- zac
- sacl phase
- lac one,8 ; make and store frequency address in memory
- sub one
- sacl freq
- lac freq,4
- tblr freq ; read PLL initial frequency
- larp 0
- lark ar0,7
- lack armfilt
- tblr h10
- add one
- tblr h11
- ; Okay the BS is over lets get to work !
-
- wait: bioz fire ; is it time for a new sample
- b wait ; nope go wait in the corner
- fire: in xn0,pa3 ; get a new sample here
- ; as the following routines have a variable length
- lac xn0,4
- sub one,15 ; Change ADC format to two's complement
- sacl xn0
- banz ntyt
- out data,pa7
- lac contr
- add one
- and one
- sacl contr
- dont: out contr,pa5
- lark ar0,7
- ntyt: lac tester,6
- addh masko
- sach yn0
- out yn0,pa4 ; send wefax tone to the speaker
-
- ; end output
-
- ; Now begin demodulator
- lack one
- sacl modem ; store control that makes complex tone
- lack one ;
- sacl mps ; Restore sine and cosine quadrant multipliers
- sacl mpc ;
- lac phase
- call tones ; go make complex tone
- lac sine
- sacl tester
-
- lt xn0 ; load the current sample
- mpy cosine; multiply by cosine
- pac
- sach yn0,1 ; store it Q channel current sample
- mpy sine ; multiply sample by sine
- pac
- sach xn0,1 ; now store it in current sample place for I channel
-
- ; Low pass for each sample cutoff is at 400 Hz. >1000Hz is 30+ db down
- ; Roll off is smooth between 400 and 1000.
-
- ; First lowpass I arm product
-
- zac
- ;
- lt xn23
- mpyk -717
- ;
- ltd xn22
- mpyk -214
- ;
- ltd xn21
- mpyk -337
- ;
- ltd xn20
- mpyk -903
- ;
- ltd xn19
- mpyk -865
- ;
- ltd xn18
- mpyk -57
- ;
- ltd xn17
- mpyk -1356
- ;
- ltd xn16
- mpyk -1855
- ;
- ltd xn15
- mpyk -479
- ;
- ltd xn14
- mpyk 2845
- ;
- ltd xn13
- mpy h10
- ;
- ltd xn12
- mpy h11
- ;
- ltd xn11
- mpy h11
- ;
- ltd xn10
- mpy h10
- ;
- ltd xn9
- mpyk 2845
- ;
- ltd xn8
- mpyk -479
- ;
- ltd xn7
- mpyk -1855
- ;
- ltd xn6
- mpyk -1356
- ;
- ltd xn5
- mpyk -57
- ;
- ltd xn4
- mpyk 865
- ;
- ltd xn3
- mpyk 903
- ;
- ltd xn2
- mpyk 337
- ;
- ltd xn1
- mpyk -214
- ;
- ltd xn0
- mpyk -717
- ;
- apac
- ;
- sach xn0,1
-
- ; Now do the Q arm
- ;
-
- zac
- ;
- lt yn23
- mpyk -717
- ;
- ltd yn22
- mpyk -214
- ;
- ltd yn21
- mpyk -337
- ;
- ltd yn20
- mpyk -903
- ;
- ltd yn19
- mpyk -865
- ;
- ltd yn18
- mpyk -57
- ;
- ltd yn17
- mpyk -1356
- ;
- ltd yn16
- mpyk -1855
- ;
- ltd yn15
- mpyk -479
- ;
- ltd yn14
- mpyk 2845
- ;
- ltd yn13
- mpy h10
- ;
- ltd yn12
- mpy h11
- ;
- ltd yn11
- mpy h11
- ;
- ltd yn10
- mpy h10
- ;
- ltd yn9
- mpyk 2845
- ;
- ltd yn8
- mpyk -479
- ;
- ltd yn7
- mpyk -1855
- ;
- ltd yn6
- mpyk -1356
- ;
- ltd yn5
- mpyk -57
- ;
- ltd yn4
- mpyk 865
- ;
- ltd yn3
- mpyk 903
- ;
- ltd yn2
- mpyk 337
- ;
- ltd yn1
- mpyk -214
- ;
- ltd yn0
- mpyk -717
- ;
- apac
- ;
- sach yn0,1
- ; Okay we now have filtered products with data bauding pseudo base banded
- ; Let's close the loop and lock on
- lac xn0; Hard limit data line for phase error detector
- bgez pdps ; is data baud a plus one ?
- lt yn0 ; get ready for a multiply
- mpyk -1 ; multiply phase error arm by -1
- pac
- b ny ; go close the loop
- pdps: lac yn0
- ny: sacl c0 ; store sign corrected phase error.
-
- ; error updates are computed compute new phase and freq
-
- lac c0,13 ; make phase gain 1/8 of phase error
- sach cosy ;
- lac cosy ;
- bgez delph ; is phase error nonnegative?
- add one,15 ; No so bring it back from -angle to between 0 & 2*PI
- delph: add phase ; add the old phase
- add freq ; add the phase increment (frequency)
- and mask ; modulo 2*pi
- sacl phase ; store it for next sample complex tone generation step
- lac xn0
- bgz posd
- lt mone
- mpy xn0
- pac
- posd: sacl data
- b wait ; go output and then do it again
-
- ; complex tone generator if modem>0 if modem<0 sine wave generator
-
- tones: sacl wkph ; store a working copy
- lac wkph,4
- subh one
- blz getem ; is it in a quadrant bigger than first?
- subh one
- bgez thfr; is it in a quadrant greater than two?
- lac 1,13 ; nope so load pi
- sub wkph ; subtract phase so that it maps back into 1st quad
- sacl wkph ; store
- lac mone ; load -1
- sacl mpc ; store it in the cosine multiplier
- b getem ; go read tables
- thfr: lac mone ; multiplier for bottom half
- sacl mps ; store
- lac wkph ;
- sub one,13 ; map angle back to upper half and go do it again
- b tones
- getem: lac wkph,10 ; take 1st quadrant phase equiv for sine and pick
- ; off coarse part of phase address
- sach coph ; store it
- lack sintbl ; load sine table offset into accumulator
- add coph ; add coarse address off set
- tblr sinx ; read the coarse sine value
- lac one,6 ; load pi/2
- sub coph ; subtract the coarse phase to get cosines offset
- sacl coph
- lack sintbl
- add coph ; do same as above for coarse cosine
- tblr cosx
- lac wkph ; load working phase
- and maskl ; mask off fine addres
- sacl coph ; store it
- lack fines ; locate fine table offset
- add coph ; add for offset into fine table
- tblr siny ; read table
- lack finec
- add coph
- tblr cosy
- zac
- lt sinx ; load sinx
- mpy cosy ; multiply by cosy
- lta siny ; load t reg with fine sin and accumulate previous prod.
- mpy cosx ; multiply by coarse cosx to use sin(X+Y)
- apac ; add the result to coarse sine
- sach sine ; store it.
- lac modem
- blz mult
- lac 1,12 ; load full address pi/2
- sub wkph ; subtract the working phase to get cosine
- sacl wkph
- lac wkph,10 ; from here to the later MARK it is identical to above
- sach coph
- lack sintbl
- add coph
- tblr sinx
- lac one,6
- sub coph
- sacl coph
- lack sintbl
- add coph
- tblr cosx
- lac wkph
- and maskl
- sacl coph
- lack fines
- add coph
- tblr siny
- lack finec
- add coph
- tblr cosy
- zac
- lt cosy
- mpy sinx
- lta siny
- mpy cosx
- apac ; MARK
- sach cosine ; store it in the cosine
- mult: lt mps; now we need to do a few multiplies by sign changes due to
- mpy sine ; to quadrant part of phase address
- pac; multiply sine by sine sign (:-) and
- sacl sine ; store the result
- lac modem
- bgz cosm
- ret
- cosm: mpy cosine; now multiply cosine by the same
- pac
- sacl cosine ; store it
- lt mpc; load cosine differentiator from sine sign (:-)
- mpy cosine; multiply
- pac
- sacl cosine ; store
- ret
- end
- ; Ebbly Ebbly Ebbly thats all folks
-